interface DebounceOptions {
  immediate?: boolean;   // 是否立即执行
  trailing?: boolean;    // 是否在延迟后执行最后一次
}
export function debounce<T extends (...args: any[]) => any>(
  func: T,
  wait: number,
  options: DebounceOptions = {}
): {
  (this: ThisParameterType<T>, ...args: Parameters<T>): void;
  cancel: () => void;
} {
  let timeout: ReturnType<typeof setTimeout> | null = null;
  let lastArgs: Parameters<T> | null = null;

  const debounced = function (this: ThisParameterType<T>, ...args: Parameters<T>) {
    lastArgs = args;

    if (timeout) clearTimeout(timeout);

    if (options.immediate && !timeout) {
      func.apply(this, args);
    }

    timeout = setTimeout(() => {
      timeout = null;
      if (!options.immediate && options.trailing !== false) {
        func.apply(this, lastArgs!);
      }
      lastArgs = null;
    }, wait);
  };

  debounced.cancel = () => {
    if (timeout) {
      clearTimeout(timeout);
      timeout = null;
    }
  };

  return debounced as typeof debounced;
}